package ExistController;
/**
 * Classe que permite la interacción con una base de datos exist
 * @author Miguel Delgado Rodríguez
 */

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;

import java.util.List;

import javax.xml.transform.OutputKeys;

//import org.exist.xquery.update.Insert;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.Database;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XPathQueryService;


public class BDController {
	protected static String URI = "xmldb:exist://localhost:8080/exist/xmlrpc/PXC_DB";
	public static Collection col;
	public static XPathQueryService service;
	public static Utils ut;
	public static String dir = "localhost:8080";

	public BDController()
	{
		ut = new Utils();
	}


	/**
	 * Establece una comunicación entre la clase y el servidor de la base de datos exist 
	 * @throws Exception
	 */
	public static void connect() throws Exception {
		String driver = "org.exist.xmldb.DatabaseImpl";
		// initialize database driver
		Class<?> cl = null;
		try {
			cl = Class.forName(driver);
		} catch (Exception e) {
			System.out.println("EXCEPTION: " + e.getMessage());
		}
		Database database = null;
		try {
			database = (Database) cl.newInstance();
		} catch (InstantiationException e) {
			throw new Exception("Error en inicialitzacio del driver2");
		} catch (IllegalAccessException e) {
			throw new Exception("Error en inicialitzacio del driver3");
		}
		try {
			DatabaseManager.registerDatabase(database);
		} catch (XMLDBException e) {
			throw new Exception("Error en inicialitzacio del driver4");
		}
		try {
			String URI = getURI();
			System.out.println("Conectado a URI: "+ URI);
			col = DatabaseManager.getCollection(URI);
			col.setProperty(OutputKeys.INDENT, "no");
			service = (XPathQueryService) col.getService("XPathQueryService",
			"1.0");
			service.setProperty("indent", "yes");
		} catch (XMLDBException e) {
			throw new Exception("Error en XMLDB");
		}
	}


	/**
	 * Configura la IP y puerto del servidor EXist
	 * 
	 * @param IP Contiene un String con la IP del servidor eXist
	 * @param port Contiene el puerto en el que está escuchando el servidor
	 */
	public void setIpPort(String IP, String port)
	{
		dir = IP+":"+port;
	}

	private static String getURI()
	{
		return "xmldb:exist://"+dir+"/exist/xmlrpc/PXC_DB";
	}


	/**
	 * Hace una consulta a la Base de datos
	 * @param query Contiene un String con la consulta en lenguaje XQuery
	 * @param comma Si comma esta activado el string resultado se concatena con "," entre sus terminos
	 * @return Devuelve el resultado de la consulta o ""i no si es una insert/update/delete
	 * @throws Exception
	 */
	private static String doQuery(String query,boolean comma) throws Exception {
		String res = "";
		try {
			ResourceSet result = service.query(query);
			ResourceIterator i;
			i = result.getIterator();
			while (i.hasMoreResources()) {
				Resource r = i.nextResource();
				res = res.concat((String) r.getContent());
				if(comma){ res.concat(",");}
			}
		} catch (Exception e) {
			throw new Exception("Query Error");
		}
		return res;

	}


	/**
	 * Permite insertar un usuario en el registro.
	 * 
	 * @param nombre Contiene el nombre del usuario que se quiere introducir
	 * @param Apellidos Contiene uno o varios apellidos del usuario
	 * @param dni Es la clave primaria de la tabla de usuarios y contiene su numero de identificacion y la letra sin espacios
	 * @param direccion Contiene la residencia del usuario, o donde se encuentra el PC alquilado/contratista
	 * @return Devuelve un String donde se especifica si la Query ha ido bien o no.
	 * @throws Exception
	 */
	public String insertUsuario(String nombre, String Apellidos, String pass, String rol, String dni, String direccion ) throws Exception
	{
		int numID = Integer.parseInt(doQuery("/Usuario/usuarios/ids/text()",false));

		if(doQuery("/Usuario/usuarios/persona[dni =\""+dni+"\"]/nombre/text()",false).compareTo("")==0){ // Comprovación clave primaria
			doQuery("update insert <persona><nombre>"+nombre+"</nombre><Apellidos>"+Apellidos+"</Apellidos><password>"+pass+"</password><Rol>"+rol+"</Rol><dni>"+dni+"</dni><direccion>"+direccion+"</direccion><pcId>"+(numID+1)+"</pcId></persona> into /Usuario/usuarios",false);
			doQuery("update replace /Usuario/usuarios/ids/text() with \""+(numID+1)+"\"",false);
		}
		else{ return "Error: Ya Existe un usuario con dni: "+dni; }
		return "Usuario insertado correctamente";
	}

	/**
	 * Borra el Usuario con dni igual al parametro dni
	 * 
	 * @param dni Contiene el dni del usuario que queremos eliminar
	 * @return Devuelve un String informativo sobre si se ha borrado correctamente o no
	 * @throws Exception
	 */
	public String removeUsuario(String dni) throws Exception
	{
		if(doQuery("/Usuario/usuarios/persona[dni =\""+dni+"\"]/nombre/text()",false).compareTo("")!=0){ // Comprovación clave primaria
			doQuery("update delete /Usuario/usuarios/persona[dni=\""+dni+"\"]",false);
			int numID = Integer.parseInt(doQuery("/Usuario/usuarios/ids/text()",false));
			doQuery("update replace /Usuario/usuarios/ids/text() with \""+(numID-1)+"\"",false);
		}
		else{
			return "No existe ningún usuario con dni: "+dni;
		}
		return "Usuario Borrado correctamente";
	}

	/**
	 * 
	 * @param dni Contiene el dni identificador del cliente
	 * @return Devuelve true si existe el usuario, false si no existe
	 * @throws Exception
	 */
	public boolean ExisteUsuario(String dni) throws Exception
	{
		String res = doQuery("/Usuario/usuarios/persona[dni=\""+dni+"\"]", false);
		return res.compareTo("")!=0;
	}

	/**
	 * Obtenemos un Usuario con un dni dado
	 * 
	 * @param dni Contiene el dni del Usuario que obtendremos
	 * @return Devuelve un objeto de tipo Usuario con dni dado con los datos obtenidos de la base de datos 
	 * @throws Exception
	 */
	public Usuario getUsuario(String dni) throws Exception
	{
		Usuario usr = new Usuario();
		String res = doQuery("/Usuario/usuarios/persona[dni=\""+dni+"\"]", false);
		if(res.compareTo("")!=0){
			usr = parseUser(res);
		}
		return usr;
	}

	/**
	 * Obtenemos una lista de todos los usuarios del sistema
	 * 
	 * @return Devuelve una lista de objetos usuarios, que se encontraban en la base de datos
	 * @throws Exception
	 */
	public List<Usuario> getTodosUsers() throws Exception
	{
		List<Usuario> lUs = new ArrayList<Usuario>();
		String res = doQuery("/Usuario/usuarios/persona" , false);

		String ac = res;
		while( ac.length() > 0){
			String persona = ut.parseTag("persona", ac);
			int index = persona.length()+5+7*2;
			ac = ac.substring(index);
			lUs.add(parseUser("<persona>"+persona+"</persona>"));
		}
		return lUs;
	}


	/**
	 * Permite insertar un PC en la base de datos
	 * 
	 * @param dniCli Contiene el dni del cliente propietario del pc introducido
	 * @param cpu Contiene el nombre y modelo del procesador
	 * @param memoria Se especifica como un mumero seguido de la unidad de medida, ej:"1 GB"
	 * @param discoduro Guarda el valor del tamaño del disco duro del PC, en el mismo formato que para memoria
	 * @return Devuelve un String donde se explica si se ha insertado correctamente o no.
	 * @throws Exception
	 */
	public String insertPC(String dniCli, String cpu, String memoria, String discoduro) throws Exception
	{
		String id = doQuery("/Usuario/usuarios/persona[dni=\""+dniCli+"\"]/pcId/text()",false); 
		if( id.compareTo("")!=0){
			if(doQuery("/DatosTecnicos/usrs/PC[id=\""+id+"\"]",false).compareTo("")==0){
				doQuery("update insert  <PC><id>"+id+"</id><cpu>"+cpu+"</cpu><memoria>"+memoria+"</memoria><discoduro>"+discoduro+"</discoduro></PC> into /DatosTecnicos/usrs",false);
			}
			else{
				return "Error: Ya existe un PC con id: "+id;
			}
		}
		else{ 
			return "No existe ningún usuario que tenga asignado id:"+ id;
		}
		return "PC insertado correctamente";
	}

	/**
	 * Permite borrar un PC de la base de datos
	 * 
	 * @param id Contiene el valor del id del PC que queremos borrar
	 * @return Devuelve un String con el resultado de la petición de borrar
	 * @throws Exception
	 */
	public String removePC(String id) throws Exception
	{
		if(doQuery("/DatosTecnicos/usrs/PC[id=\""+id+"\"]/cpu/text()",false).compareTo("")!=0)
		{
			doQuery("update delete /DatosTecnicos/usrs/PC[id=\""+id+"\"]",false);
		}
		else{
			return "No existe el PC con id: "+id;
		}
		return "PC borrado correctamente";
	}


	/**
	 * Obtenemos un DatosTecnicos con una id dada
	 * 
	 * @param id Contiene el id del PC que queremos obtener
	 * @return Devuelve un objeto de la clase DatosTecnicos con una id dada y los datos obtenidos de la base de datos
	 * @throws Exception
	 */
	public DatosTecnicos getPc(String id) throws Exception
	{
		DatosTecnicos dt = new DatosTecnicos();
		String res = doQuery("/DatosTecnicos/usrs/PC[id=\""+id+"\"]", false);
		if(res.compareTo("")!=0){
			dt = parsePC(res); 
		}
		return dt;
	}

	/**
	 * Inserta un Tarea en el conjunto de trabajos
	 * 
	 * @param nifEmpresa Contiene el nif de la empresa contratante
	 * @param dniAlqui Contiene la dni del usuario propietario del pc alquilado
	 * @param fechaEnvio Representa la fecha en que el servidor envia la tarea al pc alquilado
	 * @param fechaFin Es la fecha en que el pc ha acabado su tarea.
	 * @param nomIm Contiene el nombre de la imagen que se procesa 
	 * @return Devuelve un String con el estado en que ha acabado la consulta 
	 * @throws Exception
	 */
	public String insertTarea(String nifEmpresa, String dniAlqui, String fechaEnvio,String fechaFin, String nomIm , int x , int y) throws Exception
	{
		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);

		if( idEmpresa.compareTo("")!=0 ){
			if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and idalquilado=\""+dniAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\" and idsubimage/y=\""+y+"\" ]", false).compareTo("")==0){
				doQuery("update insert <trabajo><idcontratista>"+idEmpresa+"</idcontratista><idalquilado>"+dniAlqui+"</idalquilado><fechaenvio>"+fechaEnvio+"</fechaenvio><fechafin>"+fechaFin+"</fechafin><nombreIm>"+nomIm+"</nombreIm><idsubimage><x>"+x+"</x><y>"+y+"</y></idsubimage><resultado></resultado></trabajo> into /Trabajos",false);
				return "tarea insertada";
			}
			return "Ya existe una tarea para: "+nomIm+"con subimagen:"+x+" "+y;
		}
		else return "la empresa: "+nifEmpresa+" no existe";
	}

	/**
	 * Añade una posición encontrada a un trabajo
	 * 
	 * @param nifEmpresa Contiene el nif de la empresa contratante
	 * @param dniAlqui Contiene el dni del usuario alquilado
	 * @param x Representa la coordenada x del pixel encontrado
	 * @param y Representa la coordenada y del pixel encontrado
	 * @param nomIm Es el nombre de la imagen que se procesa en el trabajo
	 * @param subimax Contiene la coordenada x de la subimagen de trabajo definido
	 * @param subimay Contiene la coordenada x de la subimagen de trabajo definido
	 * @return Devuelve un String con el estado en que ha acabado la consulta
	 * @throws Exception
	 */
	public String insertPos(String nifEmpresa, String dniAlqui, int x, int y, String nomIm, int subimax, int subimay) throws Exception 
	{
		String idAlqui = doQuery("/Usuario/usuarios/persona[dni=\""+dniAlqui+"\"]/pcId/text()",false);
		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);

		if( idAlqui.compareTo("")!=0  && idEmpresa.compareTo("")!=0 ){

			if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+subimax+"\" and idsubimage/y=\""+subimay+"\" ]", false).compareTo("")!=0){
				doQuery("update insert <pos><x>"+x+"</x><y>"+y+"</y></pos> into /Trabajos/trabajo[idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+subimax+"\" and idsubimage/y=\""+subimay+"\"]/resultado",false);
				return "Pos añadida";
			}
			return "No existe el trabajo";
		}
		else return "El usuario con dni "+ dniAlqui+ " no existe o la empresa: "+nifEmpresa+" no existe";
	}

	/**
	 * Introduce una lista de resultados en un Trabajo concreto
	 * 
	 * @param results Contiene la lista de puntos x,y para introducir en el Trabajo concreto
	 * @param nifEmpresa Contiene el nif de la empresa contratante
	 * @param dniAlqui Contiene el dni del usuario alquilado
	 * @param nomIm Es el nombre de la imagen que se procesa en el trabajo
	 * @param subimax Contiene la coordenada x de la subimagen de trabajo definido
	 * @param subimay Contiene la coordenada x de la subimagen de trabajo definido
	 * @return Devuelve un String con el estado en que ha acabado la consulta
	 * @throws Exception
	 */
	public String insertResultado(List<String> results, String nifEmpresa, String dniAlqui,String nomIm, int subimax, int subimay) throws Exception
	{
		String idAlqui = doQuery("/Usuario/usuarios/persona[dni=\""+dniAlqui+"\"]/pcId/text()",false);
		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);


		String puntos = "";
		ListIterator<String> it = results.listIterator();

		while(it.hasNext())
		{
			puntos = puntos.concat("<pos><x>"+it.next()+"</x><y>"+it.next()+"</y></pos>");
		}

		if( idAlqui.compareTo("")!=0  && idEmpresa.compareTo("")!=0 ){

			if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+subimax+"\" and idsubimage/y=\""+subimay+"\" ]", false).compareTo("")!=0){

				if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+subimax+"\" and idsubimage/y=\""+subimay+"\" ]/resultado/pos/x/text()", false).compareTo("")==0){
					doQuery("update delete /Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+subimax+"\" and idsubimage/y=\""+subimay+"\" ]/resultado",false);
					doQuery("update insert <resultado>"+puntos+"</resultado> into /Trabajos/trabajo[idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+subimax+"\" and idsubimage/y=\""+subimay+"\"]",false);
					return "Lista de resultados Obtenida";
				}
				else{
					ListIterator<String> it2 = results.listIterator();
					while(it2.hasNext())
					{
						insertPos(nifEmpresa, dniAlqui, Integer.parseInt(it2.next()), Integer.parseInt(it2.next()), nomIm, subimax, subimay);
					}
					return "Lista añadida punto a punto";
				}
			}
			return "No existe el trabajo";
		}
		else{
			return "El cliente o el contratista no existen";
		}
	}

	/**
	 * Obtenemos el trabajo especificado por sus identificadores
	 * 
	 * @param nifEmpresa Contiene la id del pc contratante
	 * @param idalqui Contiene la id del pc alquilado
	 * @param nombreIm Es el nombre de la imagen que se procesa en el trabajo
	 * @param x Representa la coordenada x donde empieza la subimagen respecto la imagen global
	 * @param y Representa la coordenada y donde empieza la subimagen respecto la imagen global
	 * @return Devuelve un Objeto de tipo Trabajo con el contenido de los campos del trabajo
	 * @throws Exception
	 */
	public Trabajo getTrabajo(String nifEmpresa, String idalqui, String nombreIm, int x, int y) throws Exception
	{		
		Trabajo tr = new Trabajo();

		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);
		if(idEmpresa.compareTo("")!=0){
			String res = doQuery("/Trabajos/trabajo[idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idalqui+"\" and nombreIm=\""+nombreIm+"\" and idsubimage/x/text()=\""+x+"\" and idsubimage/y/text()=\""+y+"\"]", false);
			tr = parseTrabajo(res);
			tr.Res = getResultado(idEmpresa, idalqui, nombreIm, x, y);
		}

		return tr;
	}

	/**
	 * Se Obtiene la lista de ficheros en los que ha trabajado el pc con una id dada
	 * 
	 * @param idAlqui Contiene la id del px alquilado
	 * @return Devuelve una lista con cada uno de los nombre de imagenes procesadas
	 * @throws Exception
	 */
	public List<String> getTrabajosIdAlq(String idAlqui) throws Exception
	{
		List<String> Trabajos = new ArrayList<String>();

		String a = doQuery("let $trabs := /Trabajos/trabajo[idalquilado="+idAlqui+"] for $tr in $trabs return $tr/nombreIm/text()",true);
		String[] listarguments = a.split(",");

		for(int i=0; i< listarguments.length; i++)
		{
			Trabajos.add(listarguments[i]);
			System.out.println(listarguments[i]+" ");
		}

		return Trabajos;
	}


	/**
	 * Obtiene la lista de los ficheros en que ha trabajado el usuarios con un dni dado
	 * 
	 * @param dni Contiene el dni del usuario
	 * @return Devuelve una lista con los nombres de los ficheros en que ha participado el usuario dado
	 * @throws Exception
	 */
	public List<String> getTrabajosDni(String dni) throws Exception
	{
		List<String> Trabajos = new ArrayList<String>();

		String id = doQuery("/Usuario/usuarios/persona[dni=\""+dni+"\"]/pcId/text()", false);

		if(id.compareTo("")!=0) Trabajos = getTrabajosIdAlq(id);

		return Trabajos;
	}


	/**
	 * Devuelve una lista de trabajos pendiente
	 * 
	 * @return Devolvemos una lista de objetos de tipo Trabajo
	 */
	public List<Trabajo> getTrabajosPendientes() throws Exception
	{
		List<Trabajo> Trabajos = new ArrayList<Trabajo>();

		String res = doQuery("/Trabajos/trabajo[idalquilado=\"null\"]", false);

		String ac = res;
		while( ac.length() > 0){
			String trab = ut.parseTag("trabajo", ac);
			int index = trab.length()+5+7*2;
			ac = ac.substring(index);
			Trabajos.add(parseTrabajo("<trabajo>"+trab+"</trabajo>"));
		}

		return Trabajos;
	}

	/**
	 * Obtenemos los diferentes puntos x,y del resultado 
	 * 
	 * @param nifEmpresa Contiene el nif de la empresa contratante
	 * @param idAlqui Contiene la id del pc alquilado
	 * @param nomIm Es el nombre de la imagen tratada
	 * @param x Es el identificador x que indica donde empieza la subimagen respecto la imagen global
	 * @param y Es el identificador y que indica donde empieza la subimagen respecto la imagen global
	 * @return Devuelve un objeto Resultado con la lista de puntos x,y
	 * @throws Exception
	 */
	public Resultado getResultado(String nifEmpresa, String idAlqui, String nomIm,int x, int y) throws Exception
	{
		Resultado Res = new Resultado();

		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);

		if( idEmpresa.compareTo("")!=0 ){
			String a = doQuery("/Trabajos/trabajo[idcontratista=\""+idEmpresa+"\" and idalquilado=\""+idAlqui+"\"  and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\" and idsubimage/y=\""+y+"\"]/resultado/pos", false);

			List<String> xs = new ArrayList<String>();
			xs = ut.getText("x","pos","<posiciones>"+a+"</posiciones>");
			List<String> ys = new ArrayList<String>();
			ys = ut.getText("y","pos", "<posiciones>"+a+"</posiciones>");

			for(int c=0; c< xs.size();c++)
			{
				Res.addPos(new Pos( Integer.parseInt(xs.get(c)) , Integer.parseInt(ys.get(c)) ) );
			}
		}
		return Res;
	}

	/**
	 * Obtenemos todos los trabajos de una imagen dada
	 * 
	 * @param nomIm Contiene el nombre de la imagen
	 * @return Devuelve una lista de Trabajos de la imagen con nombreimagen pasado como parametro
	 * @throws Exception
	 */
	public List<Trabajo> getTrabajosImagen(String nomIm) throws Exception
	{
		List<Trabajo> trabajos = new ArrayList<Trabajo>();

		String Trabs = doQuery("/Trabajos/trabajo[nombreIm=\""+nomIm+"\" ]", false);

		String ac = Trabs;
		while( ac.length() > 0){
			String trab = ut.parseTag("trabajo", ac);
			int index = trab.length()+5+7*2;
			ac = ac.substring(index);
			trabajos.add(parseTrabajo("<trabajo>"+trab+"</trabajo>"));
		}
		return trabajos;
	}
	
	/**
	 * Obtenemos el numero de puntos procesados de una imagen
	 * @param nomIm Contiene el nombre de la imagen
	 * @return Devuelve un entero con el numero de puntos
	 * @throws Exception
	 */
	public int calculaPuntosObtenidos(String nomIm) throws Exception
	{
		List<Trabajo> trabajos = getTrabajosImagen(nomIm);
				
		int points = 0;
		ListIterator<Trabajo> it = trabajos.listIterator();
		while(it.hasNext())
		{
			points += it.next().Res.getNumPoints();			
		}
		
		return points;		
	}
	
	/**
	 * Obtenemos el numero de puntos procesados de una imagen
	 * @param nomIm Contiene el nombre de la imagen
	 * @return Devuelve un entero con el numero de puntos
	 * @throws Exception
	 */
	public int getPuntosObtenidos(String nomIm) throws Exception
	{
		int points = 0;
		ImagesData im = getImagesData(nomIm);
		if(im.getNombre()!=null) points = im.getnumpoints();
		return points;
	}

	/**
	 * Modificamos la fecha y asignamos un trabajo a un cliente
	 * 
	 * @param nifEmpresa Contiene la id del pc contratante
	 * @param nomIm Contiene el nombre de la imagen general que se procesa
	 * @param x Describe la coordenada x donde empieza la subimagen respecto la general 
	 * @param y Describe la coordenada y donde empieza la subimagen respecto la general
	 * @param fechaEnv Contiene la fecha en que se ha asignado la tarea
	 * @param dniClient Representa el dni del cliente al que se le ha asignado la tarea
	 * @return Devuelve un String con información de como se ha ido la acción
	 * @throws Exception
	 */
	public String setTrabajo(String nifEmpresa, String nomIm, int x, int y, String fechaEnv, String dniClient) throws Exception
	{
		Usuario us = getUsuario(dniClient);
		String idalqui = us.getPcid();

		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);

		if(idEmpresa.compareTo("")!=0){
			if(idalqui!=null && doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\"  and idsubimage/y=\""+y+"\" ]", false).compareTo("")!=0){
				doQuery("update replace /Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\"  and idsubimage/y=\""+y+"\" ]/idalquilado/text() with \""+idalqui+"\"", false);
				doQuery("update replace /Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\"  and idsubimage/y=\""+y+"\" ]/fechaenvio/text() with \""+fechaEnv+"\"", false);
				return "Modificación efectuada con exito";
			}
			else{ 
				return "Trabajo no existe o Usuario inexistente. ";
			}
		}
		else
		{
			return "La empresa con nifEmpresa: "+nifEmpresa+" no existe";
		}
	}

	/**
	 * Indicamos que el trabajo indicado por parametros ya se ha terminado de procesar
	 * 
	 * @param nifEmpresa Contiene el nif de la empresa contratante
	 * @param nomIm Contiene el nombre de la imagen general que se procesa
	 * @param x Describe la coordenada x donde empieza la subimagen respecto la general
	 * @param y Describe la coordenada y donde empieza la subimagen respecto la general
	 * @param fechaFin Contiene la fecha en que se ha acabado de procesar la faena
	 * @param dniClient Representa el dni del cliente al que se le ha asignado la tarea
	 * @throws Exception
	 */
	public String finTrabajo(String nifEmpresa, String nomIm, int x, int y, String fechaFin, String dniClient) throws Exception
	{
		boolean confirmFinish = false;

		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);

		if( idEmpresa.compareTo("")!=0){
			// Modificamos la fecha de fin del trabajo
			if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\"  and idsubimage/y=\""+y+"\" ]", false).compareTo("")!=0){

				if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\"  and idsubimage/y=\""+y+"\" and fechafin=\"null\" ]", false).compareTo("")!=0){
					doQuery("update replace /Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idsubimage/x=\""+x+"\"  and idsubimage/y=\""+y+"\" ]/fechafin/text() with \""+fechaFin+"\"", false);
					confirmFinish = true;
				}
			}

			// Comprovamos si se ha acabado de procesar todas las partes de una imagen
			if(doQuery("/Trabajos/trabajo[ idcontratista=\""+idEmpresa+"\" and nombreIm=\""+nomIm+"\" and idalquilado=\"null\"]", false).compareTo("")==0 && confirmFinish)
			{	// Ya no quedan trabajos pendientes de esta imagen
				doQuery("update replace /ImagesData/Image[nombre=\""+nomIm+"\"]/acabado/text() with \"1\" ", false);
				doQuery("update replace /ImagesData/Image[nombre=\""+nomIm+"\"]/fechaFin/text() with \""+fechaFin+"\" ", false);
				
				// modificamos el numero de puntos que ha procesado la imagen
				int puntos = calculaPuntosObtenidos(nomIm);
				doQuery("update replace /ImagesData/Image[nombre=\""+nomIm+"\"]/numpuntos/text() with \""+puntos+"\" ", false);
			}		
		}
		else{
			return "La empresa con NIF: "+nifEmpresa+"no existe."; 
		}
		return "Fin trabajo ejecutado con exito.";
	}


	/**
	 * Inserta una nueva imagen en el sistema
	 * 
	 * @param nombre Contiene el nombre y extension del fichero de imagen
	 * @param nifEmpresa Representa el dni del usuario contratante
	 * @param fechaInsert Contiene la fecha cuando se ingreso la imagen en el sistema 
	 * @param acabado Indica si la imagen se ha acabado de procesar
	 * @param fechaFin Indica la fecha en que se acabo de procesar, si no se ha acabado será vacio
	 * @param path Indica la ruta donde se encuentra la imagen
	 * @return Devuelve un String informativo del estado de la llamada
	 * @throws Exception
	 */
	public String insertImageData(String nombre, String nifEmpresa, String fechaInsert,boolean acabado,  String fechaFin, String path ) throws Exception
	{
		String acab = acabado? "1":"0";

		String idEmpresa = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);

		if(doQuery("/ImagesData/Image[nombre =\""+nombre+"\"]", false).compareTo("")==0){
			doQuery("update insert  <Image><nombre>"+nombre+"</nombre><idcontratante>"+idEmpresa+"</idcontratante><fechaInsert>"+fechaInsert+"</fechaInsert><acabado>"+acab+"</acabado><fechaFin>"+fechaFin+"</fechaFin><path>"+path+"</path><numpuntos>0</numpuntos></Image> into /ImagesData", false);
			return "ImageData Insertada correctamente";
		}
		else return "Ya existe una imagen con nombre: "+nombre;
	}


	/**
	 * Borra una imagen de la base de datos
	 * 
	 * @param nombre Contiene el nombre y extension del fichero de imagen
	 * @return Devuelve un String informativo del estado de la llamada
	 * @throws Exception
	 */
	public String removeImageData(String nombre) throws Exception
	{
		if( doQuery("/ImagesData/Image[nombre =\""+nombre+"\"]", false).compareTo("")!=0)
		{
			doQuery("update delete /ImagesData/Image[nombre =\""+nombre+"\"]", false);
			return "ImageData borrada satisfactoriamente";
		}
		else{ return "No existe la imagen con nombre:"+ nombre; }
	}

	/**
	 * Obtenemos el ImageData con un nombre dado
	 * 
	 * @param nombre Contiene el nombre y extension del fichero de imagen
	 * @return Devuelve un objeto de tipo ImagesData con los datos obtenidos 
	 * @throws Exception
	 */
	public ImagesData getImagesData(String nombre) throws Exception
	{	
		ImagesData imD = new ImagesData();
		String res = doQuery("/ImagesData/Image[nombre =\""+nombre+"\"]", false);
		if(res.compareTo("")!=0){
			imD = parseImage(res);
		}
		return imD;
	}

	/**
	 * Obtenemos una lista con las imagenes que ha entrado en el sistema un Usuario contratante dado
	 * 
	 * @param idContratante Representa la id del usuario contratante
	 * @return Devolvemos una lista de ImagesData con las imagenes obtenidas del Usuario con id IdContratante
	 * @throws Exception
	 */
	public List<ImagesData> getImDataContr(String nifEmpresa) throws Exception
	{
		List<ImagesData> list = new ArrayList<ImagesData>();

		String idContratante = doQuery("/Usuario/usuarios/persona[dni=\""+nifEmpresa+"\"]/pcId/text()",false);
		if( idContratante.compareTo("")!=0 ){

			String res = doQuery("/ImagesData/Image[idcontratante=\""+idContratante+"\"]", false);
			
			String ac = res;
			while( ac.length() > 0){
				String Image = ut.parseTag("Image", ac);
				int index = Image.length()+5+5*2;
				ac = ac.substring(index);
				list.add(parseImage("<Image>"+Image+"</Image>"));
			}
		}
		return list;
	}



	/**
	 * Obtenemos un objeto de parsear el contenido de una cadena dada
	 * 
	 * @param res Contiene el texto XML del usuario
	 * @return Devuelve un objeto Usuario con los datos dados
	 */
	private Usuario parseUser(String res)
	{
		Usuario usr = new Usuario();
		String nombre = ut.parseTagValue("nombre", res);
		String apellidos = ut.parseTagValue("Apellidos", res);
		String password = ut.parseTagValue("password", res);
		String rol = ut.parseTagValue("Rol", res);
		String dni = ut.parseTagValue("dni", res);
		String direccion = ut.parseTagValue("direccion", res);
		String pcId = ut.parseTagValue("pcId", res);
		usr = new Usuario(nombre, apellidos, password, rol , dni, direccion, pcId );
		return usr;
	}

	/**
	 * Obtenemos un DatosTecnicos de una cadena que contiene XML
	 * 
	 * @param res Contiene la cadena con texto en formato XML para tratar
	 * @return Devuelve un objeto de tipo DatosTecnicos con los valores de sus parametros
	 */
	private DatosTecnicos parsePC(String res)
	{
		DatosTecnicos dt = new DatosTecnicos();
		String id = ut.parseTagValue("id", res);
		String cpu = ut.parseTagValue("cpu", res);
		String memoria = ut.parseTagValue("memoria", res);
		String discoduro = ut.parseTagValue("discoduro", res);
		dt = new DatosTecnicos(id, cpu, memoria, discoduro);
		return dt;
	}

	private Trabajo parseTrabajo(String res) throws Exception
	{
		Trabajo tr = new Trabajo();
		String idcont = ut.parseTagValue("idcontratista", res);
		String idalqui = ut.parseTagValue("idalquilado", res);
		String nombreIm = ut.parseTagValue("nombreIm", res);
		String fechenv = ut.parseTagValue("fechaenvio", res);
		String fechfin = ut.parseTagValue("fechafin", res);
		int x = Integer.parseInt(ut.parseTagValue("idsubimage/x", res));
		int y = Integer.parseInt(ut.parseTagValue("idsubimage/y", res));
		
		tr = new Trabajo(idcont,idalqui,fechenv,fechfin,nombreIm,x,y);
		
		String nifEmpresa = doQuery("/Usuario/usuarios/persona[pcId=\""+idcont+"\"]/dni/text()",false);
		tr.Res = getResultado(nifEmpresa, idalqui, nombreIm, x, y);
		
		return tr;
	}

	/**
	 * Dado un String que contiene los tags XML de un ImageData, devuelve un objeto ImagesData
	 * 
	 * @param res Es una cadena de caracteres que contiene datos en formato XML de una imagen
	 * @return Devuelve un objeto ImagesData con los datos obtenidos del String XML
	 */
	private ImagesData parseImage(String res)
	{
		ImagesData im = new ImagesData();
		String nombre = ut.parseTagValue("nombre", res);
		String idContratante= ut.parseTagValue("idcontratante", res);
		String path= ut.parseTagValue("path", res);
		String acabado= ut.parseTagValue("acabado", res);
		String fechaInsert= ut.parseTagValue("fechaInsert", res);
		String fechaFin= ut.parseTagValue("fechaFin", res);
		String numpoints= ut.parseTagValue("numpuntos", res);
		boolean acab = acabado.compareTo("1")==0? true: false;
		im = new ImagesData(nombre, idContratante, path, acab, fechaInsert, fechaFin,numpoints);

		return im;
	}



}
